package com.cyt.sys.util;

import com.cyt.base.util.DateUtil;
import com.cyt.base.util.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author rong yuan
 */
public class EntryUtils {

    public static void copyProperties(Object source, Object target) {
        Field[] fields = target.getClass().getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            String fieldType = checkFieldTypeByName(fields[i].getName().toString(), source);
            if (StringUtils.isNotBlank(fieldType)) {
                String fieldValue;
                Object object = getFieldValueByName(fields[i].getName().toString(), source);
                if (object == null) {
                    fieldValue = null;
                } else {
                    if ("Date".equals(fieldType)) {
                        fieldValue = parseDateToString((Date) object);
                    } else {
                        fieldValue = String.valueOf(object);
                    }
                }
                setFieldValueByName(fieldValue, fields[i].getName().toString(), fields[i].getType(), target);
            }
        }
    }

    private static String checkFieldTypeByName(String fieldName, Object source) {
        Field[] fields = source.getClass().getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            if (fieldName.equals(fields[i].getName().toString())) {
                return fields[i].getType().getSimpleName();
            }
        }
        return "";
    }

    private static Object getFieldValueByName(String fieldName, Object source) {
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method method = source.getClass().getMethod(getter, new Class[]{});
            return method.invoke(source, new Object[]{});
        } catch (Exception e) {
            return null;
        }
    }

    private static void setFieldValueByName(String fieldValue, String fieldName, Class fieldType, Object target) {
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String setter = "set" + firstLetter + fieldName.substring(1);
            Method method = target.getClass().getMethod(setter, new Class[]{fieldType});
            if ("String".equals(fieldType.getSimpleName())) {
                method.invoke(target, fieldValue);
            } else if ("Date".equals(fieldType.getSimpleName())) {
                method.invoke(target, parseStringToDate(fieldValue));
            } else if ("Integer".equals(fieldType.getSimpleName()) || "int".equals(fieldType.getSimpleName())) {
                method.invoke(target, Integer.parseInt(fieldValue));
            } else if ("Long".equalsIgnoreCase(fieldType.getSimpleName())) {
                method.invoke(target, Long.parseLong(fieldValue));
            } else if ("Double".equalsIgnoreCase(fieldType.getSimpleName())) {
                method.invoke(target, Double.parseDouble(fieldValue));
            } else if ("Boolean".equalsIgnoreCase(fieldType.getSimpleName())) {
                method.invoke(target, Boolean.parseBoolean(fieldValue));
            } else if ("BigDecimal".equalsIgnoreCase(fieldType.getSimpleName())) {
                method.invoke(target, new BigDecimal(fieldValue));
            }
        } catch (Exception e) {
        }
    }


    private static Date parseStringToDate(String fieldValue) {
        if (StringUtils.isBlank(fieldValue)) {
            return null;
        } else {
            if (fieldValue.split(":").length > 1) {
                return new SimpleDateFormat(DateUtil.DATE_TIME_PATTERN).parse(fieldValue, new ParsePosition(0));
            } else {
                return new SimpleDateFormat(DateUtil.DATE_PATTERN).parse(fieldValue, new ParsePosition(0));
            }
        }
    }

    private static String parseDateToString(Date fieldValue) {
        if (fieldValue == null) {
            return null;
        } else {
            return DateUtil.convertDateToString(DateUtil.DATE_TIME_PATTERN, fieldValue);
        }
    }
}